package org.example.mq.mqserver.datacenter;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zaxxer.hikari.HikariDataSource;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.example.mq.common.constants.MQConstants;
import org.example.mq.mqserver.core.Bind;
import org.example.mq.mqserver.core.Exchange;
import org.example.mq.mqserver.core.ExchangeType;
import org.example.mq.mqserver.core.MessageQueue;
import org.example.mq.mqserver.mapper.BindMapper;
import org.example.mq.mqserver.mapper.ExchangeMapper;
import org.example.mq.mqserver.mapper.MessageQueueMapper;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

/*
 * 针对数据控制类
 */
@Slf4j
@Component
public class DataBaseManager implements DisposableBean {
    @Autowired
    private BindMapper bindMapper;
    @Autowired
    private ExchangeMapper exchangeMapper;
    @Autowired
    private MessageQueueMapper messageQueueMapper;
    @Autowired
    private DataSource dataSource;

    private HikariDataSource ds;
    // 初始化 ds 的逻辑...
    @Override
    public void destroy() {
        if (ds != null && !ds.isClosed()) {
            ds.close();
        }
    }

    //初始化
    public void init(){
        File file = new File("./data/meta.db");
        //检查数据库 meta.db文件是否存在
        if(!checkDBExists(file)){
            //创建目录
            File parentDir = file.getParentFile();
            if (!parentDir.exists()) {
                parentDir.mkdirs();  // 递归创建目录
            }

            //建表操作
            createTable();
            //创建默认交换机
            createDefaultData();
        }
        else {
            //数据库存在不做任何操作
        }
    }

    public void closeInit() throws InterruptedException {
        //将meta.db文件删除
        //在这之前应该关闭DataBaseManager，否则会导致文件无法删除
        // 1. 关闭连接池
        if (dataSource instanceof HikariDataSource) {
            ((HikariDataSource) dataSource).close();
        }
        // 触发一次 GC，尽量释放底层资源
        System.gc();
        Thread.sleep(200);
    }

    private void createDefaultData() {
        List<Exchange> exchanges = new ArrayList<>();

        exchanges.add(new Exchange(MQConstants.AMQ_DIRECT_EXCHANGE, ExchangeType.DIRECT, true, false));
        exchanges.add(new Exchange(MQConstants.AMQ_FANOUT_EXCHANGE, ExchangeType.FANOUT, true, false));
        exchanges.add(new Exchange(MQConstants.AMQ_TOPIC_EXCHANGE, ExchangeType.TOPIC, true, false));
        exchanges.add(new Exchange(MQConstants.AMQ_HEADERS_EXCHANGE, ExchangeType.HEADERS, true, false));
        exchanges.add(new Exchange(MQConstants.AMQ_MATCH_EXCHANGE, ExchangeType.HEADERS, true, false));
        exchanges.add(new Exchange(MQConstants.AMQ_TRACE_EXCHANGE, ExchangeType.TOPIC, true, false));
        exchanges.add(new Exchange(MQConstants.DEFAULT_EXCHANGE, ExchangeType.DIRECT, true, false)); // 默认空名交换机

        exchangeMapper.batchInsertExchange(exchanges);
        System.out.println("[默认交换机初始化完成]");
    }

    private void createTable() {
        bindMapper.createBindingTable();
        exchangeMapper.createExchangeTable();
        messageQueueMapper.createQueueTable();
        System.out.println("[数据库建表完成]");
    }

    private boolean checkDBExists(File file) {
        if(file.exists())return true;
        else return false;
    }

    //删除数据库文件
    public void deleteDB(){
        File file = new File("./data/meta.db");
        if(file.exists()){
            file.delete();
            System.out.println("[数据库文件删除成功]");
        }
        else{
            System.out.println("[数据库文件不存在]");
        }
    }



    //其他方法封装
    /*
       --------------------交换机提供增删查，不提供改
     */
    public boolean insertExchange(Exchange exchange){
        int res = 0;
        try {
            res = exchangeMapper.insert(exchange);
        } catch (Exception e) {
            if (e.getMessage() != null && e.getMessage().contains("SQLITE_CONSTRAINT_PRIMARYKEY")) {
                log.warn("插入交换机失败，主键已存在: {}", exchange.getName());
                return false;
            }
            // 如果不是主键冲突，说明是其他异常，继续抛出
            log.error("新增交换机失败:", e);
            throw new RuntimeException(e);
        }

        if(res==0)return false;
        return true;
    }

    //交换机物理删除
    public boolean deleteExchange(String name){
        try{
            exchangeMapper.deleteById(name);
            return true;
        }catch (Exception e){
            log.error("交换机删除失败",e);
            return false;
        }
    }

    public Exchange queryExchange(String name){
        return exchangeMapper.selectOne(new LambdaQueryWrapper<Exchange>().eq(Exchange::getName,name));
    }

    public List<Exchange> queryAllExchange(){
        List<Exchange> exchanges = exchangeMapper.selectList(null);

        return exchanges;
    }


    //--------------------bind 增删查
    public boolean insertBind(Bind bind){
        try{
            bindMapper.insert(bind);
            return true;
        }catch (Exception e){
            log.error("新增bind失败",e);
            return false;
        }
    }

    public boolean deleteBind(String exchangeName,String queueName,String bindingKey){
                try{
                    bindMapper.delete(new LambdaQueryWrapper<Bind>()
                           .eq(Bind::getExchangeName,exchangeName)
                           .eq(Bind::getQueueName,queueName)
                           .eq(Bind::getBindingKey,bindingKey));
                    return true;
                }catch (Exception e){
                    log.error("删除bind失败",e);
                    return false;
                }
    }

    //交换机名查询bind
    public List<Bind> queryBindByExchange(String exchangeName){
        return bindMapper.selectList(new LambdaQueryWrapper<Bind>()
               .eq(Bind::getExchangeName,exchangeName));
    }

    //队列名查询bind
    public List<Bind> queryBindByQueue(String queueName){
        return bindMapper.selectList(new LambdaQueryWrapper<Bind>()
               .eq(Bind::getQueueName,queueName));
    }

    //查询所有
    public List<Bind> queryAllBind(){
        return bindMapper.selectList(null);
    }

    //--------------------messageQueue 增删查
    public boolean insertMessageQueue(MessageQueue messageQueue){
        try{
            //这里新增队列的时候应该检查是否设置持久化，如果设置持久化应该通过MessageFileManager来新建持久化的文件


            messageQueueMapper.insert(messageQueue);
            return true;
        }catch (Exception e){
            log.error("新增messageQueue失败",e);
            return false;
        }
    }

    public boolean deleteMessageQueue(String name){
        try{
            messageQueueMapper.deleteById(name);
            return true;
        }catch (Exception e){
            log.error("删除messageQueue失败",e);
            return false;
        }
    }

    //查询所有消息队列
    public List<MessageQueue> queryAllMessageQueue(){
        return messageQueueMapper.selectList(null);
    }

}
